﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AAA.DataSource;
using AAA.DesignPattern.Observer;
using AAA.Meta.Quote.Data;
using AAA.Base.Util;

namespace AAA.TradeLanguage
{
    public class DefaultDataAccess : IDataAccess
    {
        private IDataSource _dataSource;
        private string _strActiveSymbol;
        public DataSourceChangeEvent OnDataSourceChange;
        private CurrentTime _currentTime;

        public CurrentTime CurrentTime
        {
            get
            {
                return _currentTime;
            }
            set
            {
                _currentTime = value;
            }

        }

        #region IDataAccess Members

        public IDataSource DataSource
        {
            get
            {
                return _dataSource;
            }
            set
            {
                IDataSource oldDataSource = _dataSource;
                _dataSource = value;
                if (OnDataSourceChange != null)
                    OnDataSourceChange(oldDataSource, value);
/*
                if (value == null && _dataSource != null)
                    _dataSource.Detach(this);

                _dataSource = value;

                if (_dataSource != null)
                    _dataSource.Attach(this);
 */ 
            }
        }

        public string ActiveSymbol
        {
            get
            {
                return _strActiveSymbol;
            }
            set
            {
                _strActiveSymbol = value;
            }
        }

        private object GetValue(string strType, string strSymbolId, int iIndex)
        {
            try
            {
                if (_dataSource.ContainsSymbol(strSymbolId) == false)
                    return float.NaN;

                List<BarRecord> lstBarData;
                BarRecord barRecord;
                lstBarData = DataSource.GetBar(strSymbolId);
                int iCurreintIndex = _currentTime == null
                                        ? lstBarData.Count - 1
                                        : _currentTime.GetDataIndex(strSymbolId);

                if (iCurreintIndex < iIndex)
                    return float.NaN;

                barRecord = lstBarData[iCurreintIndex - iIndex];
                BarData barData = new BarData(barRecord);

                switch (strType)
                {
                    case "Time":
                        return barData.BarDateTime;

                    case "Open":
                        return barData.Open;

                    case "High":
                        return barData.High;

                    case "Low":
                        return barData.Low;

                    case "Close":
                        return barData.Close;

                    case "Volume":
                        return barData.Volume;

                    case "Amount":
                        return barData.Amount;

                    case "BarNumber":
                        return iCurreintIndex - iIndex;

                    case "BarCompression":
                        return new BarCompression(barData.BarCompression, barData.CompressionInterval);

                    case "Bar":
                        return barRecord;
                }
            }
            catch (Exception ex)
            {
            }
            return float.NaN;
        }

        public BarCompression BarCompression(string strSymbolName)
        {
            try
            {
                return (BarCompression)GetValue("BarCompression", strSymbolName, 0);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public DateTime Time()
        {
            return Time(0);
        }

        public DateTime Time(int iIndex)
        {
            return Time(ActiveSymbol, iIndex);
        }

        public DateTime Time(string strSymbolId, int iIndex)
        {

            object oReturn = GetValue("Time", strSymbolId, iIndex);

            try
            {
                if (float.IsNaN((float)oReturn))
                    return DateTime.MinValue;
            }
            catch {}
            return (DateTime)oReturn;
        }

        public BarRecord Bar()
        {
            return Bar(0);
        }

        public BarRecord Bar(int iIndex)
        {
            return Bar(ActiveSymbol, iIndex);
        }

        public BarRecord Bar(string strSymbolId, int iIndex)
        {
            object oReturn = GetValue("Bar", strSymbolId, iIndex);

            try
            {
                if (float.IsNaN((float)oReturn))
                    return null;
            }
            catch { }
            return (BarRecord)oReturn;
        }

        public float Open()
        {
            return Open(0);
        }

        public float Open(int iIndex)
        {
            return Open(ActiveSymbol, iIndex);
        }

        public float Open(string strSymbolId, int iIndex)
        {
            return (float)GetValue("Open", strSymbolId, iIndex);
        }

        public float High()
        {
            return High(0);
        }

        public float High(int iIndex)
        {
            return High(ActiveSymbol, iIndex);
        }

        public float High(string strSymbolId, int iIndex)
        {
            return (float)GetValue("High", strSymbolId, iIndex);
        }


        public float Low()
        {
            return Low(0);
        }

        public float Low(int iIndex)
        {
            return Low(ActiveSymbol, iIndex);
        }

        public float Low(string strSymbolId, int iIndex)
        {
            return (float)GetValue("Low", strSymbolId, iIndex);
        }


        public float Close()
        {
            return Close(0);
        }

        public float Close(int iIndex)
        {
            return Close(ActiveSymbol, iIndex);
        }

        public float Close(string strSymbolId, int iIndex)
        {
            return (float)GetValue("Close", strSymbolId, iIndex);
        }


        public float Volume()
        {
            return Volume(0);
        }

        public float Volume(int iIndex)
        {
            return Volume(ActiveSymbol, iIndex);
        }

        public float Volume(string strSymbolId, int iIndex)
        {
            return (float)GetValue("Volume", strSymbolId, iIndex);
        }


        public float Amount()
        {
            return Amount(0);
        }

        public float Amount(int iIndex)
        {
            return Amount(ActiveSymbol, iIndex);
        }

        public float Amount(string strSymbolId, int iIndex)
        {
            return (float)GetValue("Amount", strSymbolId, iIndex);
        }

        public float TickCount()
        {
            return TickCount(0);
        }

        public float TickCount(int iIndex)
        {
            return TickCount(ActiveSymbol, iIndex);
        }

        public float TickCount(string strSymbolId, int iIndex)
        {
            return (float)GetValue("TickCount", strSymbolId, iIndex);
        }

        public int BarNumber()
        {
            return BarNumber(0);
        }

        public int BarNumber(int iIndex)
        {
            return BarNumber(ActiveSymbol, iIndex);
        }

        public int BarNumber(string strSymbolId, int iIndex)
        {
            return (int)GetValue("BarNumber", strSymbolId, iIndex);
        }


        public float GetValue(string strFunctionName, int iIndex)
        {
            throw new NotImplementedException();
        }

        public void SetGlobalVariable(string strKey, float fValue)
        {
            throw new NotImplementedException();
        }

        public float GetGlobalVariable(string strKey)
        {
            throw new NotImplementedException();
        }

        public float GetGlobalVariable(string strKey, int iIndex)
        {
            throw new NotImplementedException();
        }

        public void AddBarData(string strSymbolName, BarRecord barRecord)
        {
            List<BarRecord> lstBarRecord;
            if (_dataSource.GetBar(strSymbolName) == null)
                _dataSource.AddSymbol(strSymbolName, new List<BarRecord>());

            lstBarRecord = _dataSource.GetBar(strSymbolName);

            if (lstBarRecord.Count == 0)
            {
                lstBarRecord.Add(barRecord);
            }
            else
            {
                if (lstBarRecord[lstBarRecord.Count - 1].BarDateTime.CompareTo(barRecord.BarDateTime) == 0)
                    UpdateLastBarData(strSymbolName, barRecord);
                else
                    lstBarRecord.Add(barRecord);
            }
        }

        public void UpdateLastBarData(string strSymbolName, BarRecord barRecord)
        {
            if (_dataSource.GetBar(strSymbolName) == null)
                return;

            List<BarRecord> lstBarData = _dataSource.GetBar(strSymbolName);
            lstBarData[lstBarData.Count - 1].Update(barRecord);
/*
            lstBarData[lstBarData.Count - 1].V0 = barRecord.V0;
            lstBarData[lstBarData.Count - 1].V1 = barRecord.V1;
            lstBarData[lstBarData.Count - 1].V2 = barRecord.V2;
            lstBarData[lstBarData.Count - 1].V3 = barRecord.V3;
            lstBarData[lstBarData.Count - 1].V4 = barRecord.V4;
            lstBarData[lstBarData.Count - 1].V5 = barRecord.V5;            
*/
  
        }

        #endregion
    }
}
